/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.diplomka.datalayer.daoimpl;

import cz.muni.fi.diplomka.datalayer.dao.TileDao;
import cz.fi.muni.diplomka.common.Coordinates;
import cz.fi.muni.diplomka.common.enumeration.TileType;
import cz.muni.fi.diplomka.datalayer.entity.TileEntity;
import cz.muni.fi.diplomka.datalayer.util.DbConnector;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Jakub Kutil
 */
public class TileDaoImpl implements TileDao {

    private Connection con = null;
    private PreparedStatement ps = null;
    private ResultSet rs = null;

    public TileDaoImpl() {
    }

    @Override
    public void addTile(TileEntity tileEntity) {
        if (tileEntity == null) {
            throw new IllegalArgumentException("TileEntity can not be null");
        }
        try {
            con = DbConnector.getDBConnection();
            String insert = "INSERT INTO tile"
                    + "(x_coordinate, y_coordinate, type) VALUES"
                    + "(?,?,?)";
            ps = con.prepareStatement(insert);


            ps.setLong(1, tileEntity.getCoordinates().getX_coordinate());
            ps.setLong(2, tileEntity.getCoordinates().getY_coordinate());
            ps.setString(3, tileEntity.getType().toString());

            ps.executeUpdate();

            rs = ps.getGeneratedKeys();
            rs.next();


        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
    }

    @Override
    public void editTile(TileEntity tileEntity) {
        if (tileEntity == null) {
            throw new IllegalArgumentException("TileEntity can not be null");
        }
        try {
            con = DbConnector.getDBConnection();
            String update = "UPDATE tile SET type=? WHERE x_coordinate=? AND y_coordinate=?";

            ps = con.prepareStatement(update);

            ps.setString(1, tileEntity.getType().toString());
            ps.setInt(2, tileEntity.getCoordinates().getX_coordinate());
            ps.setInt(3, tileEntity.getCoordinates().getY_coordinate());

            ps.executeUpdate();
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
    }

    @Override
    public void deleteTile(Coordinates coordinates) {
        if (coordinates == null) {
            throw new IllegalArgumentException("Coordinates can not be null");
        }
        try {
            con = DbConnector.getDBConnection();
            String delete = "DELETE FROM tile WHERE x_coordinate=? AND y_coordinate=?";

            ps = con.prepareStatement(delete);

            ps.setLong(1, coordinates.getX_coordinate());
            ps.setLong(2, coordinates.getY_coordinate());

            ps.executeUpdate();
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
    }

    @Override
    public List<TileEntity> getAllTiles() {
        List<TileEntity> tileList = new ArrayList<TileEntity>();

        try {
            con = DbConnector.getDBConnection();
            String getAllTiles = "SELECT * FROM tile";

            ps = con.prepareStatement(getAllTiles);

            rs = ps.executeQuery();

            while (rs.next()) {
                TileEntity tile = new TileEntity();
                Coordinates coordinates = new Coordinates();
                coordinates.setX_coordinate(rs.getInt("x_coordinate"));
                coordinates.setY_coordinate(rs.getInt("Y_coordinate"));
                tile.setCoordinates(coordinates);
                tile.setType(TileType.valueOf(rs.getString("type")));

                tileList.add(tile);

            }
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
        return tileList;
    }

    @Override
    public List<TileEntity> getSquareOfTiles(int x, int y) {
        List<TileEntity> squareOfTilesList = new ArrayList<TileEntity>();

        try {
            con = DbConnector.getDBConnection();
            String getSquareOfTiles = "SELECT * FROM tile WHERE x_coordinate BETWEEN ? AND ? AND y_coordinate BETWEEN ? AND ?";

            ps = con.prepareStatement(getSquareOfTiles);
            ps.setInt(1, x);
            if (x > -10 && x <= 0) {
                ps.setInt(2, x + 10);
            } else {
                ps.setInt(2, x + 9);
            }

            if (y < 10 && y >= 0) {
                ps.setInt(3, y - 10);
            } else {
                ps.setInt(3, y - 9);
            }
            ps.setInt(4, y);

            rs = ps.executeQuery();

            while (rs.next()) {
                TileEntity tile = new TileEntity();
                Coordinates coordinates = new Coordinates();
                coordinates.setX_coordinate(rs.getInt("x_coordinate"));
                coordinates.setY_coordinate(rs.getInt("Y_coordinate"));
                tile.setCoordinates(coordinates);
                tile.setType(TileType.valueOf(rs.getString("type")));

                squareOfTilesList.add(tile);
            }
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
        return squareOfTilesList;

    }

    @Override
    public List<TileEntity> getAllTilesOfType(String type) {
        if (type == null) {
            throw new IllegalArgumentException("Type can not be null");
        }
        List<TileEntity> tileListOfType = new ArrayList<TileEntity>();

        try {
            con = DbConnector.getDBConnection();
            String getAllTilesOfType = "SELECT * FROM tile WHERE type=?";

            ps = con.prepareStatement(getAllTilesOfType);
            ps.setString(1, type);

            rs = ps.executeQuery();

            while (rs.next()) {
                TileEntity tile = new TileEntity();
                Coordinates coordinates = new Coordinates();
                coordinates.setX_coordinate(rs.getInt("x_coordinate"));
                coordinates.setY_coordinate(rs.getInt("Y_coordinate"));
                tile.setCoordinates(coordinates);
                tile.setType(TileType.valueOf(rs.getString("type")));

                tileListOfType.add(tile);

            }
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
        return tileListOfType;
    }

    @Override
    public Coordinates getUpperLeftCorner() {
        Coordinates coordinates = new Coordinates();

        try {
            con = DbConnector.getDBConnection();
            String getUpperLeftCorner = "SELECT MIN(x_coordinate), MAX(y_coordinate) FROM tile";

            ps = con.prepareStatement(getUpperLeftCorner);

            rs = ps.executeQuery();

            while (rs.next()) {
                coordinates.setX_coordinate(rs.getInt(1));
                coordinates.setY_coordinate(rs.getInt(2));
            }
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
        return coordinates;
    }

    @Override
    public Coordinates getLowerRightCorner() {
        Coordinates coordinates = new Coordinates();

        try {
            con = DbConnector.getDBConnection();
            String getUpperLeftCorner = "SELECT MAX(x_coordinate), MIN(y_coordinate) FROM tile";

            ps = con.prepareStatement(getUpperLeftCorner);

            rs = ps.executeQuery();

            while (rs.next()) {
                coordinates.setX_coordinate(rs.getInt(1));
                coordinates.setY_coordinate(rs.getInt(2));
            }
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
        return coordinates;
    }

    @Override
    public TileEntity getTileAtPosition(int x, int y) {
        TileEntity tile = new TileEntity();

        try {
            con = DbConnector.getDBConnection();
            String getTileAtPosition = "SELECT * FROM tile WHERE x_coordinate=? AND y_coordinate=?";

            ps = con.prepareStatement(getTileAtPosition);
            ps.setInt(1, x);
            ps.setInt(2, y);

            rs = ps.executeQuery();

            while (rs.next()) {
                Coordinates c = new Coordinates();
                c.setX_coordinate(rs.getInt("x_coordinate"));
                c.setY_coordinate(rs.getInt("Y_coordinate"));
                tile.setCoordinates(c);
                tile.setType(TileType.valueOf(rs.getString("type")));
            }
        } catch (SQLException ex) {
            Logger.getLogger(TileDaoImpl.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DbConnector.closeConnection(rs, ps, con);
        }
        return tile;
    }
}
